#include <QApplication>
#include <QMainWindow>
#include <QTableView>
#include <QSqlDatabase>
#include <QSqlTableModel>
#include <QSqlQuery>
#include <QSqlError>
#include <QSortFilterProxyModel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QComboBox>
#include <QLabel>
#include <QInputDialog>
#include <QMessageBox>
#include <QThread>
#include <QObject>
#include <QElapsedTimer>
#include <algorithm>
#include <QRandomGenerator>
#include <QDir>
#include<QHeaderView>
#include<QDebug>
// 1. SQLite数据库配置（文件型数据库，无需服务器）
const QString DB_FILE = "./school.db";  // 数据库文件路径（当前目录下）
const QString DB_TABLE = "scores";      // 数据表名

// 2. 子线程工作类：处理耗时操作（数据加载、数据库导入）
class ScoreWorker : public QObject {
    Q_OBJECT

public:
    explicit ScoreWorker(QObject *parent = nullptr) : QObject(parent) {}

public slots:
    // 模拟批量数据加载（生成测试数据）
    void loadBulkData() {
        QElapsedTimer timer;
        timer.start();

        // 模拟延迟
        QThread::msleep(800);

        // 生成1000行模拟数据
        QVector<QVector<QString>> data;
        for (int i = 0; i < 1000; ++i) {
            data.append({
                QString("S%1").arg(1000 + i, 3, 10, QChar('0')),
                QString("学生%1").arg(i + 1),
                (i % 3 == 0) ? "数学" : (i % 3 == 1) ? "英语" : "物理",
                QString::number(60 + QRandomGenerator::global()->bounded(40))
            });
        }

        emit bulkDataLoaded(data);
        emit operationFinished(QString("批量数据生成完成，耗时：%1 ms").arg(timer.elapsed()));
    }

    // 批量导入数据到SQLite（子线程执行）
    void importToDatabase(const QVector<QVector<QString>>& data) {
        QElapsedTimer timer;
        timer.start();

        // 1. 建立SQLite连接（子线程单独连接）
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "importConnection");
        db.setDatabaseName(DB_FILE);  // SQLite只需指定数据库文件

        if (!db.open()) {
            emit operationFinished("数据库连接失败：" + db.lastError().text());
            return;
        }

        // 2. 批量插入（使用事务提高效率）
        QSqlQuery query(db);
        db.transaction();  // 开始事务

        // 清空现有数据（可选）
        if (!query.exec(QString("DELETE FROM %1").arg(DB_TABLE))) {
            db.rollback();
            emit operationFinished("清空表失败：" + query.lastError().text());
            db.close();
            return;
        }

        // 批量插入新数据
        int successCount = 0;
        for (const auto& row : data) {
            if (row.size() != 4) continue;

            // SQLite插入SQL（字段与MySQL兼容）
            QString sql = QString(
                "INSERT INTO %1 (student_id, name, subject, score) "
                "VALUES ('%2', '%3', '%4', %5)"
            ).arg(DB_TABLE, row[0], row[1], row[2], row[3]);

            if (query.exec(sql)) {
                successCount++;
            } else {
                qDebug() << "插入失败：" << query.lastError().text() << "SQL:" << sql;
            }
        }

        // 提交事务
        if (db.commit()) {
            emit operationFinished(
                QString("导入完成：成功%1条，失败%2条，耗时%3 ms")
                .arg(successCount).arg(data.size() - successCount).arg(timer.elapsed())
            );
        } else {
            db.rollback();
            emit operationFinished("事务提交失败：" + db.lastError().text());
        }

        // 关闭连接
        db.close();
        QSqlDatabase::removeDatabase("importConnection");
    }

signals:
    void bulkDataLoaded(const QVector<QVector<QString>>& data);
    void operationFinished(const QString& message);
};

// 3. 主窗口类：连接SQLite并支持数据管理
class ScoreManager : public QMainWindow {
    Q_OBJECT

public:
    ScoreManager(QWidget *parent = nullptr) : QMainWindow(parent) {
        setWindowTitle("QTableView + SQLite 数据管理系统");
        setMinimumSize(900, 600);

        // 初始化线程和工作对象
        workerThread = new QThread(this);
        worker = new ScoreWorker();
        worker->moveToThread(workerThread);
        workerThread->start();

        // 初始化数据库模型（连接SQLite）
        if (!initDatabaseModel()) {
            QMessageBox::critical(this, "数据库错误", "无法初始化数据库连接，程序将退出！");
            qApp->quit();
        }

        // 创建UI
        createUI();
        connectSignals();
    }

    ~ScoreManager() {
        workerThread->quit();
        workerThread->wait();
        delete worker;
    }

private:
    // 初始化SQLite数据库模型
    bool initDatabaseModel() {
        // 1. 检查SQLite驱动是否可用（Qt默认包含，无需额外编译）
        if (!QSqlDatabase::isDriverAvailable("QSQLITE")) {
            QMessageBox::critical(nullptr, "驱动错误", "未找到SQLite驱动！");
            return false;
        }

        // 2. 建立SQLite连接（主线程）
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(DB_FILE);  // 指定数据库文件（不存在会自动创建）

        if (!db.open()) {
            QMessageBox::critical(nullptr, "连接失败", "SQLite连接失败：" + db.lastError().text());
            return false;
        }

        // 3. 检查数据表是否存在，不存在则创建
        QSqlQuery query;
        QString createTableSql = QString(
            "CREATE TABLE IF NOT EXISTS %1 ("
            "id INTEGER PRIMARY KEY AUTOINCREMENT,"  // SQLite自增主键
            "student_id TEXT NOT NULL,"              // 学号（文本类型）
            "name TEXT NOT NULL,"                    // 姓名
            "subject TEXT NOT NULL,"                 // 科目
            "score INTEGER NOT NULL)"                // 分数
        ).arg(DB_TABLE);

        if (!query.exec(createTableSql)) {
            QMessageBox::critical(nullptr, "建表失败", "创建数据表失败：" + query.lastError().text());
            return false;
        }

        // 4. 创建SQL模型并绑定表
        sqlModel = new QSqlTableModel(this, db);
        sqlModel->setTable(DB_TABLE);
        sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange);  // 实时同步
        // 映射字段到表头（跳过id列）
        sqlModel->setHeaderData(1, Qt::Horizontal, "学号");
        sqlModel->setHeaderData(2, Qt::Horizontal, "姓名");
        sqlModel->setHeaderData(3, Qt::Horizontal, "科目");
        sqlModel->setHeaderData(4, Qt::Horizontal, "分数");
        sqlModel->select();  // 加载数据

        // 5. 创建代理模型（排序筛选）
        proxyModel = new QSortFilterProxyModel(this);
        proxyModel->setSourceModel(sqlModel);
        proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
        proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);

        return true;
    }

    void createUI() {
        QWidget *centralWidget = new QWidget(this);
        QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
        mainLayout->setSpacing(15);
        mainLayout->setContentsMargins(10, 10, 10, 10);

        // 状态标签
        statusLabel = new QLabel(QString("就绪：已连接到SQLite数据库（%1）").arg(DB_FILE), this);
        statusLabel->setStyleSheet("color: blue; padding: 5px; border: 1px solid #ccc;");
        mainLayout->addWidget(statusLabel);

        // 表格视图
        tableView = new QTableView(this);
        tableView->setModel(proxyModel);
        tableView->hideColumn(0);  // 隐藏id列
        tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        tableView->setEditTriggers(QAbstractItemView::DoubleClicked);
        tableView->setSortingEnabled(true);
        mainLayout->addWidget(tableView);

        // 操作按钮区
        QHBoxLayout *btnLayout = new QHBoxLayout();
        addBtn = new QPushButton("手动添加行", this);
        delBtn = new QPushButton("删除选中行", this);
        bulkLoadBtn = new QPushButton("生成测试数据", this);
        importBtn = new QPushButton("导入到数据库", this);
        btnLayout->addWidget(addBtn);
        btnLayout->addWidget(delBtn);
        btnLayout->addWidget(bulkLoadBtn);
        btnLayout->addWidget(importBtn);
        mainLayout->addLayout(btnLayout);

        // 筛选区
        QHBoxLayout *filterLayout = new QHBoxLayout();
        QLabel *filterLabel = new QLabel("筛选列：", this);
        filterColumnCombo = new QComboBox(this);
        filterColumnCombo->addItems(QStringList() << "学号" << "姓名" << "科目" << "分数");
        QLabel *keywordLabel = new QLabel("关键词：", this);
        filterKeywordEdit = new QLineEdit(this);
        filterBtn = new QPushButton("筛选", this);
        filterLayout->addWidget(filterLabel);
        filterLayout->addWidget(filterColumnCombo);
        filterLayout->addWidget(keywordLabel);
        filterLayout->addWidget(filterKeywordEdit);
        filterLayout->addWidget(filterBtn);
        mainLayout->addLayout(filterLayout);

        setCentralWidget(centralWidget);
    }

    void connectSignals() {
        // 主线程内部信号槽（DirectConnection）
        connect(addBtn, &QPushButton::clicked,
                this, &ScoreManager::addRowDialog,
                Qt::DirectConnection);

        connect(delBtn, &QPushButton::clicked,
                this, &ScoreManager::deleteSelectedRow,
                Qt::DirectConnection);

        connect(filterBtn, &QPushButton::clicked,
                this, &ScoreManager::filterTable,
                Qt::DirectConnection);

        connect(tableView->horizontalHeader(), &QHeaderView::sortIndicatorChanged,
                proxyModel, &QSortFilterProxyModel::sort,
                Qt::DirectConnection);

        // 生成测试数据（主线程→子线程）
        connect(bulkLoadBtn, &QPushButton::clicked,
                this, &ScoreManager::onBulkLoadClicked,
                Qt::DirectConnection);

        connect(this, &ScoreManager::startBulkLoad,
                worker, &ScoreWorker::loadBulkData,
                Qt::QueuedConnection);

        // 接收测试数据并更新表格（子线程→主线程）
        connect(worker, &ScoreWorker::bulkDataLoaded,
                this, &ScoreManager::onBulkDataLoaded,
                Qt::QueuedConnection);

        // 导入数据库相关（主线程→子线程）
        connect(importBtn, &QPushButton::clicked,
                this, &ScoreManager::onImportClicked,
                Qt::DirectConnection);

        connect(this, &ScoreManager::startImport,
                worker, &ScoreWorker::importToDatabase,
                Qt::QueuedConnection);

        // 子线程操作结果通知（子线程→主线程）
        connect(worker, &ScoreWorker::operationFinished,
                this, [=](const QString& msg) {
            statusLabel->setText(msg);
            bulkLoadBtn->setEnabled(true);
            importBtn->setEnabled(true);
        }, Qt::QueuedConnection);
    }

private slots:
    // 手动添加行（同步到数据库）
    void addRowDialog() {
        QString id = QInputDialog::getText(this, "添加行", "学号：");
        if (id.isEmpty()) return;

        QString name = QInputDialog::getText(this, "添加行", "姓名：");
        if (name.isEmpty()) return;

        QString subject = QInputDialog::getText(this, "添加行", "科目：");
        if (subject.isEmpty()) return;

        bool ok;
        int score = QInputDialog::getInt(this, "添加行", "分数：", 0, 0, 100, 1, &ok);
        if (!ok) return;

        // 添加到SQL模型（自动同步到SQLite）
        int row = sqlModel->rowCount();
        sqlModel->insertRow(row);
        sqlModel->setData(sqlModel->index(row, 1), id);   // student_id
        sqlModel->setData(sqlModel->index(row, 2), name); // name
        sqlModel->setData(sqlModel->index(row, 3), subject); // subject
        sqlModel->setData(sqlModel->index(row, 4), score); // score
        sqlModel->submitAll(); // 提交更改
    }

    // 删除选中行（同步到数据库）
    void deleteSelectedRow() {
        QModelIndexList selected = tableView->selectionModel()->selectedRows();
        if (selected.isEmpty()) {
            QMessageBox::warning(this, "提示", "请先选中一行！");
            return;
        }

        // 转换索引并删除
        QList<int> sourceRows;
        for (const auto& proxyIdx : selected) {
            QModelIndex sourceIdx = proxyModel->mapToSource(proxyIdx);
            sourceRows.append(sourceIdx.row());
        }
        std::sort(sourceRows.rbegin(), sourceRows.rend());

        for (int row : sourceRows) {
            sqlModel->removeRow(row);
        }
        sqlModel->submitAll(); // 提交删除
    }

    // 筛选表格
    void filterTable() {
        int col = filterColumnCombo->currentIndex() + 1; // 跳过id列（+1）
        QString keyword = filterKeywordEdit->text();
        proxyModel->setFilterKeyColumn(col);
        proxyModel->setFilterFixedString(keyword);
    }

    // 生成测试数据按钮点击
    void onBulkLoadClicked() {
        bulkLoadBtn->setEnabled(false);
        statusLabel->setText("正在生成测试数据（子线程处理中...）");
        emit startBulkLoad();
    }

    // 接收测试数据并显示
    void onBulkDataLoaded(const QVector<QVector<QString>>& data) {
        // 批量更新数据
        sqlModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
        sqlModel->removeRows(0, sqlModel->rowCount());

        for (const auto& row : data) {
            int newRow = sqlModel->rowCount();
            sqlModel->insertRow(newRow);
            sqlModel->setData(sqlModel->index(newRow, 1), row[0]);
            sqlModel->setData(sqlModel->index(newRow, 2), row[1]);
            sqlModel->setData(sqlModel->index(newRow, 3), row[2]);
            sqlModel->setData(sqlModel->index(newRow, 4), row[3]);
        }

        sqlModel->submitAll();
        sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange);
    }

    // 导入到数据库按钮点击
    void onImportClicked() {
        // 收集当前表格数据
        QVector<QVector<QString>> data;
        for (int row = 0; row < sqlModel->rowCount(); ++row) {
            QVector<QString> rowData;
            rowData.append(sqlModel->data(sqlModel->index(row, 1)).toString());
            rowData.append(sqlModel->data(sqlModel->index(row, 2)).toString());
            rowData.append(sqlModel->data(sqlModel->index(row, 3)).toString());
            rowData.append(sqlModel->data(sqlModel->index(row, 4)).toString());
            data.append(rowData);
        }

        if (data.isEmpty()) {
            QMessageBox::warning(this, "提示", "表格中没有数据可导入！");
            return;
        }

        importBtn->setEnabled(false);
        statusLabel->setText("正在导入数据到SQLite（子线程处理中...）");
        emit startImport(data);
    }

private:
    // UI组件
    QTableView *tableView;
    QPushButton *addBtn, *delBtn, *bulkLoadBtn, *importBtn, *filterBtn;
    QComboBox *filterColumnCombo;
    QLineEdit *filterKeywordEdit;
    QLabel *statusLabel;

    // 数据模型
    QSqlTableModel *sqlModel;         // 绑定SQLite表的模型
    QSortFilterProxyModel *proxyModel; // 排序筛选代理

    // 线程组件
    QThread *workerThread;
    ScoreWorker *worker;

signals:
    void startBulkLoad();    // 触发测试数据生成
    void startImport(const QVector<QVector<QString>>& data); // 触发数据库导入
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 确保程序目录可写（SQLite需要创建数据库文件）
    QDir::setCurrent(app.applicationDirPath());

    ScoreManager window;
    window.show();

    return app.exec();
}

#include "main.moc"
